package com.turman.plyopengl

import com.turman.plyopengl.data.VertexArray
import java.io.BufferedInputStream
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader

val spaceRegex = "\\s+".toRegex()

var vertexCount: Long = 0
var vertices: FloatArray? = null
var verticesRange: MutableList<Float>? = null

fun getVertexArray(inputStream: InputStream):VertexArray? {
    return if (vertices!=null) {
        VertexArray(vertices!!)
    } else {
        loadPlyData(inputStream)
        VertexArray(vertices!!)
    }
}

/**
 * 加载点云数据
 */
fun loadPlyData(inputStream: InputStream) {
    val stream = BufferedInputStream(inputStream, 0x10000)
    val reader = BufferedReader(InputStreamReader(inputStream), 0x10000)
    stream.mark(0x10000)

    var line: String
    var lineArr: List<String>
    var currentElement: MutableList<Pair<String, String>>? = null
    val elements = mutableMapOf<String, List<Pair<String, String>>>()
    val elementCounts = mutableMapOf<String, Int>()

    while (reader.readLine().also { line = it.orEmpty() } != null) {
        line = line.trim()
        if (line.isEmpty())
            continue

        lineArr = line.split(spaceRegex)
        if (lineArr.isEmpty()) {
            continue
        }

        if (lineArr[0] == "format") {
            if (line.contains("binary")) {
                //如果是二进制文件直接退出，二进制解析在此添加逻辑
                return
            }
        } else if (lineArr[0] == "element") {
            val elementName = lineArr[1]
            currentElement = mutableListOf()
            elements[elementName] = currentElement
            elementCounts[elementName] = lineArr[2].toInt()
        } else if (lineArr[0] == "property") {
            val propType = lineArr.subList(1, (lineArr.size - 1)).joinToString(" ")
            val propName = lineArr[lineArr.size - 1]
            currentElement?.add(Pair(propType, propName))
        } else if (lineArr[0] == "end_header") {
            break
        }
    }
    val tvertexCount = (elementCounts["vertex"] ?: 0).toLong()

    if (tvertexCount <= 0) {
        throw IOException("No vertices found in model.")
    }

    val tvertices = FloatArray(tvertexCount.toInt() * 6)
    val tverticesRange = mutableListOf(
        Float.MAX_VALUE,
        Float.MIN_VALUE,
        Float.MAX_VALUE,
        Float.MIN_VALUE,
        Float.MAX_VALUE,
        Float.MIN_VALUE
    )
    var x: Float
    var y: Float
    var z: Float

    for (i in 0 until tvertexCount) {
        line = reader.readLine().trim()
        if (line.isEmpty()) {
            continue
        }

        lineArr = line.split(spaceRegex)
        x = lineArr[0].toFloat()
        y = lineArr[1].toFloat()
        z = lineArr[2].toFloat()
        tvertices[i.toInt() * 6] = x
        tvertices[i.toInt() * 6 + 1] = y
        tvertices[i.toInt() * 6 + 2] = z
        tvertices[i.toInt() * 6 + 3] = lineArr[3].toFloat() / 255f
        tvertices[i.toInt() * 6 + 4] = lineArr[4].toFloat() / 255f
        tvertices[i.toInt() * 6 + 5] = lineArr[5].toFloat() / 255f
        if (x < tverticesRange[0]) {
            tverticesRange[0] = x
        } else if (x >= tverticesRange[1]) {
            tverticesRange[1] = x
        }

        if (y < tverticesRange[2]) {
            tverticesRange[2] = y
        } else if (y >= tverticesRange[3]) {
            tverticesRange[3] = y
        }

        if (z < tverticesRange[4]) {
            tverticesRange[4] = z
        } else if (z >= tverticesRange[5]) {
            tverticesRange[5] = z
        }
    }

    vertices = tvertices
    verticesRange = tverticesRange
    vertexCount = tvertexCount
}